package graph;

import java.util.HashMap;

import exception.ImpossibleTaskConfigurationException;

import task_system.Task;

public class TaskConfiguration_System extends TaskConfiguration {

	public TaskConfiguration_System(int p, int d, int c, Task t)
			throws ImpossibleTaskConfigurationException {

		super(p, d, c, t);
		this.owner = TaskConfiguration.SYSTEM;

		if (p == t.P() || d == t.D())
			throw new ImpossibleTaskConfigurationException(
					"Incompatible configuration for SYSTEM" + p + "," + d + ","
							+ c + " with task " + t.P() + "," + t.D() + ","
							+ t.C());

	}

	// Give successor node if node activated
	private TaskConfiguration_Scheduler activate()
			throws ImpossibleTaskConfigurationException {
		TaskConfiguration_Scheduler successor = null;

		if (p == 0 && d == 0 && c == 0) {
			if(task.compatibleConfiguration(p, d, c))
				successor = new TaskConfiguration_Scheduler(task.P(), task.D(),	task.C(), task);
		}

		return successor;
	}

	// Give successor node if node not activated
	private TaskConfiguration_Scheduler nonActivate()
			throws ImpossibleTaskConfigurationException {
		TaskConfiguration_Scheduler successor = null;
		if (task.compatibleConfiguration(p, d, c))
			successor = new TaskConfiguration_Scheduler(this.p(), this.d(),	this.c(), task);
		return successor;
	}

	// determines the set of node successors
	public HashMap<String, TaskConfiguration> successors() {

		HashMap<String, TaskConfiguration> successors = new HashMap<String, TaskConfiguration>();

		try {
			successors.put("Activated", activate());
			successors.put("Not Activated", nonActivate());
		} catch (ImpossibleTaskConfigurationException e) {
			e.printStackTrace();
		}

		return successors;
	}

	//
	private TaskConfiguration_Scheduler predecessorScheduled()
			throws ImpossibleTaskConfigurationException {

		int mP = Math.min(p + 1, task.P());
		int mD = mP - (task.P() - task.D());
		int mC = Math.min(c + 1, task.C());
		if (c == 0 && mD < 0 
				|| mC == c)
			return null;
		if ((((mP - mD) != (task.P() - task.D()) && mD != 0)
				|| (mD == 0 && mP > (task.P() - task.D())) 
				|| mP > task.P() || mD > task.D() || mC > task.C() 
				|| (mC < task.C() && mP == task.P() && mD == task.D())))
			return null;
		if (mD < 0)
			return new TaskConfiguration_Scheduler(mP, 0, mC, task);

		return new TaskConfiguration_Scheduler(mP, mD, mC, task);
	}

	//
	private TaskConfiguration_Scheduler predecessorNotScheduled()
			throws ImpossibleTaskConfigurationException {
		int mP = Math.min(p + 1, task.P());
		int mD = Math.max(mP - (task.P() - task.D()), 0);
		if (mD < 0)
			mD = 0;
		int mC = c;
		if(task.compatibleConfiguration(mP, mD, mC)) {
			return new TaskConfiguration_Scheduler(mP, mD, mC, task);
		}
		return null;
	}

	private TaskConfiguration_Scheduler predecessorInactive()
			throws ImpossibleTaskConfigurationException {

		if (p == 0 && d == 0 && c==0)
			if(task.compatibleConfiguration(0,0,0))
				return new TaskConfiguration_Scheduler(0, 0, 0, task);
		return null;
	}

	// Get node predecessors
	public HashMap<String, TaskConfiguration> predecessors() {
		HashMap<String, TaskConfiguration> predecessors = new HashMap<String, TaskConfiguration>();
		try {
			predecessors.put("Scheduled", predecessorScheduled());
			predecessors.put("Not Scheduled", predecessorNotScheduled());
			predecessors.put("Inactive", predecessorInactive());
		} catch (ImpossibleTaskConfigurationException e) {
			e.printStackTrace();
		}
		return predecessors;
	}

}
